We are going to replicate the results in this paper: http://www.ruf.rice.edu/~lane/papers/male_female.pdf. Take a minute to read the paper. They found that small biases in evalutations of men and women in the workplace can result in a significant underrepresntation of women in top roles.
Even more dramatic is the finding that when
sex differences explained but 1% of the variance,
an estimate that might be dismissed as
trivial, only 35% of the highest-level positions
were filled by women.
Essentially, we are going to set up a simulation of a company hierarchy with a modifiable bias factor. Then we will play out an attrition and promotion cycle to see how this affects gender distribution at different levels of the hierarchy.
Template:I've started you off with a genrateRandomPerson function, which will be used to generate all the employees of this company. In addition, I have defined a list levels, which contains the number of employees at each level, and a variable attrition, which is the percentage of employees who are replaced each cycle.
Task: Fill in the remaining functions and the main program, run the simulation and compare your results to those in the paper. Do you come up with the same results?
In [ ]:
import random
In [ ]:
def generateRandomPerson(level=0, new=True):
"""
Generates a new person (dictionary) at the specified level, and whether they are new.
Assignes random gender and preformance score (median 50, variance 10). Men get a small bias
added to increase their score.
"""
score = 0
bias = 2.1
sex = random.choice(['man', 'woman'])
if sex == 'man':
score = random.normalvariate(50, 10) + bias
else:
score = random.normalvariate(50, 10)
return {
'sex': sex,
'score': score,
'level': level,
'new': new
}
print(generateRandomPerson())
In [ ]:
def generateStaff(levels):
"""
returns list of list of employees created by generateRandom person. Each element in list should have
a list of random employees, the length should be the same as the value at that index in the levels
parameter.
Staff's level should be the index of the list they are at. new should be false.
"""
pass
In [ ]:
def allAreNew(staff):
"""
Returns true if all staff are new, false if even one original member of staff is old
"""
pass
In [ ]:
def quit(staff, attrition):
"""
Use random numbers to replace `attrition` percentage of staff with None, return staff.
"""
pass
In [ ]:
def pickBest(staff_level):
"""
returns a single employee with the best score from the list of employees in staff_level (there can be `None`s in the list)
May want to return their index too
"""
pass
In [ ]:
def promote(staff):
"""
for each level in staff replaces any none employees. If the None is in level 0, replace with a newly generated employee
from generateRandomPerson with level =0 and new=True. Otherwise pick the best employee from the previous
level using the pickBest function. The promoted employee should be deleted from the previous level (replaced with None)
and their level key should be updated with their new level. Returns updated staff (there should be no `None` employees)
"""
pass
In [ ]:
def mfratio(staff_level):
"""
For a give staff level returns a tuple of number of men, number of women, percentage men, percentage women
"""
pass
In [ ]:
# Main program
# Number of employes at each level (500 at the lowes, 10 at the highest)
levels = [500, 350, 200, 150, 100, 75, 40, 10]
attrition = 0.15
# Generate staff
# Start with a set number of iterations (5)
# run quit and then promote and update staff with the new staff
# print out the mfratio
# Once that is working, update the iteration loop, to run untill all staff are new